<?php
namespace Pinenut\Model;
/**
 * Контейнер для связей, или одной. Абстракция
 * 
 * В конструкторе передаётся прототип связи, класс сущности для связи и имя поля
 * 
 * @author Kosh
 *
 */
abstract class ReferenceContainer extends Embedded {
	
	/**
	 * Базовый тип связи
	 * @var \Pinenut\Model\Reference
	 */
	protected $_reference;
	
	/**
	 * Контейнер, или одна связь или множество
	 * @var \Pinenut\Model\Reference | \Pinenut\Model\Reference[]
	 */
	protected $_container;
	
	/**
	 * имя класса на который указывает ссылка
	 * @var \Pinenut\Model
	 */
	protected $_refClass; 
	// имя поля обратной ссылки
	protected $_refField; 
	
	
	/**
	 * Установка параметров ссылки при определении структуры модели
	 * @param \Pinenut\Model\Reference $reference
	 * @param string $className
	 * @param string $fieldName
	 */
	function __construct(Reference $reference, $refClass, $refField = null) {
		$this->_reference = $reference;	
		$this->_refClass = $refClass;
		$this->_refField = $refField;
	}
	

	
	function getEmbedded() {
		return $this->_reference;
	}
	
	
	function getReferredClass() {
		return $this->_refClass;
	}
	
	function getReferredField() {
		return $this->_refField;
	}
	

//	public function populate(array $data = array(), $fromStore = false) {
//
//		$field = $this->_reference;
//
//		$field->setParent($this);
//		$field->setField($this->_field);
//		
//		foreach ($data as $k=>&$v) {
//			if (null !== $v) {
//				$tmp = clone $field;
//				$tmp->populate($v, $fromStore);
//				$v = $tmp;
//			}
//		}
//		
//		$this->_array = $data;
//
//		return $this;
//	}
//	
//	public function toArray($forStore = false) {
//
//		$data = array();
//		
//		foreach ($this->_array as $value) {
//			$data[] = $value->toArray($forStore);
//		}
//		
//		return $data;
//	}
	
	

	
	/**
	 * Трогаем связь, если её не было, создаётся пустышка
	 * 
	 * @param string $id
	 * @param array $params
	 * @return \Pinenut\Model\Reference
	 */
	abstract protected function touchReference($id, array $params = array()); 
	
	
	/**
	 * Трогаем и нашу и обратную ссылки
	 * Рекомендованный метод для налаживания связей
	 * 
	 * @param string $id
	 * @param array $params
	 * @param array $backParams
	 * @return \Pinenut\Model\Reference
	 */
	public function prepareReference($id, array $params = array(), array $backParams = array()) {
		$reference = $this->touchReference($id, $params);
		if (null !== $this->_refField) {
			$backReference = $reference->getBackReferenceContainer()
				->touchReference($this->getModel()->_id, $backParams);
			$reference->setBackReference($backReference);
		}
	
		return $reference;
	}
	
	/**
	 * ищем, если не находим - пробуем поискать в базе
	 * 
	 * @param unknown_type $id
	 */
	abstract public function getReference($id = null);
	
	
//	{
//		// прямая связь
//		$reference = clone $this->_reference;
//		
//		if (count($params)) 
//			$reference->populate($params);
//			
//		$reference->_ref = $id;
//		
//		
//		
//		
//		$refData = $reference->toArray(true);
//		
//		// вносим изменения в базу, если они требуются
//		$this->modify()
//			->whereNot('_ref', $refData['_ref'])
//			->addToSet(null, $refData)
//			->execute();
//
//		return $reference;
//	}
}